package com.mystatusonline.webapp.action;

import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.struts2.ServletActionContext;
import org.appfuse.Constants;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;


/**
 * Base class for running Struts 2 Action tests.
 *
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
 */
public abstract class BaseActionTestCase
  extends AbstractTransactionalDataSourceSpringContextTests {

  /**
   * Transient log to prevent session synchronization issues - children can
   * use instance for logging.
   */
  protected transient final Log log = logger;
  private int smtpPort = 25250;

  /**
   * {@inheritDoc}
   */
  @Override
  protected String[] getConfigLocations() {
    super.setAutowireMode(AUTOWIRE_BY_NAME);
    return new String[]{
      "classpath:/applicationContext-resources.xml",
      "classpath:/applicationContext-dao.xml",
      "classpath:/applicationContext-service.xml",
      "classpath*:/applicationContext.xml", // for modular archetypes
      "/WEB-INF/applicationContext*.xml"
    };
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void onSetUpBeforeTransaction()
    throws Exception {
    smtpPort = smtpPort + (int)(Math.random() * 100);

    LocalizedTextUtil.addDefaultResourceBundle(Constants.BUNDLE_KEY);

    // Initialize ActionContext
    ConfigurationManager configurationManager = new ConfigurationManager();
    configurationManager.addContainerProvider(new XWorkConfigurationProvider());
    Configuration config = configurationManager.getConfiguration();
    Container container = config.getContainer();

    ValueStack stack = container.getInstance(ValueStackFactory.class)
      .createValueStack();
    stack.getContext().put(ActionContext.CONTAINER, container);
    ActionContext.setContext(new ActionContext(stack.getContext()));

    ActionContext.getContext().setSession(new HashMap<String, Object>());

    // change the port on the mailSender so it doesn't conflict with an
    // existing SMTP server on localhost
    JavaMailSenderImpl mailSender = (JavaMailSenderImpl)applicationContext
      .getBean("mailSender");
    mailSender.setPort(getSmtpPort());
    mailSender.setHost("localhost");

    // populate the request so getRequest().getSession() doesn't fail in BaseAction.java
    ServletActionContext.setRequest(new MockHttpServletRequest());
  }

  protected int getSmtpPort() {
    return smtpPort;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected void onTearDownAfterTransaction()
    throws Exception {
    ActionContext.getContext().setSession(null);
  }
}
